case GDK_VISIBILITY_NOTIFY:
case GDK_WINDOW_STATE:
case GDK_GRAB_BROKEN:
+ case GDK_DAMAGE:
gtk_widget_event (event_widget, event);
break;
{
GtkWidget *old_grab_widget;
GtkWidget *new_grab_widget;
+ gboolean was_grabbed;
+ gboolean is_grabbed;
} GrabNotifyInfo;
-static gboolean
-check_is_grabbed (GtkWidget *widget,
- GtkWidget *grab_widget)
-{
- if (grab_widget)
- return !(widget == grab_widget || gtk_widget_is_ancestor (widget, grab_widget));
- else
- return FALSE;
-}
-
static void
gtk_grab_notify_foreach (GtkWidget *child,
gpointer data)
{
GrabNotifyInfo *info = data;
- gboolean was_grabbed = check_is_grabbed (child, info->old_grab_widget);
- gboolean is_grabbed = check_is_grabbed (child, info->new_grab_widget);
+
+ gboolean was_grabbed, is_grabbed, was_shadowed, is_shadowed;
- if (was_grabbed != is_grabbed)
- {
- g_object_ref (child);
+ was_grabbed = info->was_grabbed;
+ is_grabbed = info->is_grabbed;
- _gtk_widget_grab_notify (child, was_grabbed);
-
- if (GTK_IS_CONTAINER (child))
- gtk_container_foreach (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
+ info->was_grabbed = info->was_grabbed || (child == info->old_grab_widget);
+ info->is_grabbed = info->is_grabbed || (child == info->new_grab_widget);
+
+ was_shadowed = info->old_grab_widget && !info->was_grabbed;
+ is_shadowed = info->new_grab_widget && !info->is_grabbed;
+
+ g_object_ref (child);
+
+ if (was_shadowed != is_shadowed)
+ _gtk_widget_grab_notify (child, was_shadowed);
+
+ if (GTK_IS_CONTAINER (child))
+ gtk_container_foreach (GTK_CONTAINER (child), gtk_grab_notify_foreach, info);
- g_object_unref (child);
- }
+ g_object_unref (child);
+
+ info->was_grabbed = was_grabbed;
+ info->is_grabbed = is_grabbed;
}
static void
gtk_grab_notify (GtkWindowGroup *group,
- GtkWidget *grab_widget,
- gboolean was_grabbed)
+ GtkWidget *old_grab_widget,
+ GtkWidget *new_grab_widget)
{
GList *toplevels;
GrabNotifyInfo info;
- if (was_grabbed)
- {
- info.old_grab_widget = grab_widget;
- info.new_grab_widget = group->grabs ? group->grabs->data : NULL;
- }
- else
- {
- info.old_grab_widget = (group->grabs && group->grabs->next) ? group->grabs->next->data : NULL;
- info.new_grab_widget = grab_widget;
- }
+ if (old_grab_widget == new_grab_widget)
+ return;
+
+ info.old_grab_widget = old_grab_widget;
+ info.new_grab_widget = new_grab_widget;
g_object_ref (group);
- g_object_ref (grab_widget);
toplevels = gtk_window_list_toplevels ();
g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
GtkWindow *toplevel = toplevels->data;
toplevels = g_list_delete_link (toplevels, toplevels);
+ info.was_grabbed = FALSE;
+ info.is_grabbed = FALSE;
+
if (group == gtk_window_get_group (toplevel))
- gtk_container_foreach (GTK_CONTAINER (toplevel), gtk_grab_notify_foreach, &info);
+ gtk_container_foreach (GTK_CONTAINER (toplevel),
+ gtk_grab_notify_foreach, &info);
g_object_unref (toplevel);
}
g_object_unref (group);
- g_object_unref (grab_widget);
}
void
gtk_grab_add (GtkWidget *widget)
{
GtkWindowGroup *group;
+ GtkWidget *old_grab_widget;
g_return_if_fail (widget != NULL);
group = gtk_main_get_window_group (widget);
+ if (group->grabs)
+ old_grab_widget = (GtkWidget *)group->grabs->data;
+ else
+ old_grab_widget = NULL;
+
g_object_ref (widget);
group->grabs = g_slist_prepend (group->grabs, widget);
- gtk_grab_notify (group, widget, FALSE);
+ gtk_grab_notify (group, old_grab_widget, widget);
}
}
gtk_grab_remove (GtkWidget *widget)
{
GtkWindowGroup *group;
+ GtkWidget *new_grab_widget;
g_return_if_fail (widget != NULL);
group = gtk_main_get_window_group (widget);
group->grabs = g_slist_remove (group->grabs, widget);
- g_object_unref (widget);
+ if (group->grabs)
+ new_grab_widget = (GtkWidget *)group->grabs->data;
+ else
+ new_grab_widget = NULL;
- gtk_grab_notify (group, widget, TRUE);
+ gtk_grab_notify (group, widget, new_grab_widget);
+
+ g_object_unref (widget);
}
}
SCREEN_CHANGED,
CAN_ACTIVATE_ACCEL,
GRAB_BROKEN,
+ DAMAGE_EVENT,
LAST_SIGNAL
};
klass->screen_changed = NULL;
klass->can_activate_accel = gtk_widget_real_can_activate_accel;
klass->grab_broken_event = NULL;
+ klass->damage_event = NULL;
klass->show_help = gtk_widget_real_show_help;
_gtk_marshal_VOID__ENUM,
G_TYPE_NONE, 1,
GTK_TYPE_TEXT_DIRECTION);
+
+ /**
+ * GtkWidget::grab-notify:
+ * @widget: the object which received the signal
+ * @was_grabbed: %FALSE if the widget becomes shadowed, %TRUE
+ * if it becomes unshadowed
+ *
+ * The ::grab-notify signal is emitted when a widget becomes
+ * shadowed by a GTK+ grab (not a pointer or keyboard grab) on
+ * another widget, or when it becomes unshadowed due to a grab
+ * being removed.
+ *
+ * A widget is shadowed by a gtk_grab_add() when the topmost
+ * grab widget in the grab stack of its window group is not
+ * its ancestor.
+ */
widget_signals[GRAB_NOTIFY] =
g_signal_new (I_("grab_notify"),
G_TYPE_FROM_CLASS (gobject_class),
_gtk_marshal_BOOLEAN__BOXED,
G_TYPE_BOOLEAN, 1,
GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
+ /**
+ * GtkWidget::damage-event:
+ * @widget: the object which received the signal
+ * @event: the #GdkEventExpose event
+ *
+ * Emitted when a redirected window belonging to @widget gets drawn into.
+ * The region/area members of the event shows what area of the redirected
+ * drawable was drawn into.
+ *
+ * Returns: %TRUE to stop other handlers from being invoked for the event.
+ * %FALSE to propagate the event further.
+ *
+ * Since: 2.10
+ */
+ widget_signals[DAMAGE_EVENT] =
+ g_signal_new ("damage_event",
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkWidgetClass, damage_event),
+ _gtk_boolean_handled_accumulator, NULL,
+ _gtk_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN, 1,
+ GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
/**
* GtkWidget::popup-menu
* @widget: the object which received the signal
case GDK_GRAB_BROKEN:
signal_num = GRAB_BROKEN;
break;
+ case GDK_DAMAGE:
+ signal_num = DAMAGE_EVENT;
+ break;
default:
g_warning ("gtk_widget_event(): unhandled event type: %d", event->type);
signal_num = -1;